package org.mspring.mlog.service;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FilenameUtils;
import org.mspring.mlog.entity.Album;
import org.mspring.mlog.entity.Photo;
import org.mspring.mlog.service.exception.StorageException;
import org.mspring.mlog.utils.UploadUtils;
import org.mspring.platform.utils.Size;
import org.mspring.platform.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * @author Gao Youbo
 * @since 2012-12-11
 */
@Service
public class PhotoUploadService {

    private static final Logger log = LoggerFactory.getLogger(PhotoUploadService.class);

    public static final int DEFAULT_MAX_WIDTH = 1440;
    public static final int DEFAULT_MAX_HEIGHT = 900;
    public static final int DEFAULT_MAX_PREVIEW_WIDTH = 250;
    public static final int DEFAULT_MAX_PREVIEW_HEIGHT = 250;

    public static final String PHOTO_DIRECTORY = "/photos";

    @Autowired
    private OptionService optionService;
    @Autowired
    private StorageService storageService;

    /**
     * 从request中获取MultipartFile
     *
     * @param request
     * @return
     */
    public MultipartFile getPhotoMultipartFile(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        if (fileMap == null || fileMap.size() < 1) {
            return null;
        }
        MultipartFile mf = null;
        for (Iterator<Map.Entry<String, MultipartFile>> it = fileMap.entrySet().iterator(); it.hasNext();) {
            Map.Entry<String, MultipartFile> entity = it.next();
            mf = entity.getValue();
            break;
        }
        return mf;
    }

    /**
     * 从MultipartFile中读取BufferedImage
     *
     * @param mf
     * @return
     */
    public BufferedImage getBufferedImage(MultipartFile mf) {
        try {
            return ImageIO.read(mf.getInputStream());
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 图片保存的名称
     *
     * @param mf
     * @return
     */
    public String getPhotoSaveName(MultipartFile mf) {
        return UploadUtils.getUniqueFilename() + "." + FilenameUtils.getExtension(mf.getOriginalFilename());
    }

    /**
     * 图片保存的路径
     *
     * @param photoSaveName
     * @return
     */
    public String getPhotoSavePath(String photoSaveName) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return "/photos/" + year + "/" + month + "/" + day + "/" + photoSaveName;
    }

    /**
     * 获取缩略图保存的路径
     *
     * @param photoSavePath
     * @return
     */
    public String getPhotoPreviewSavePath(String photoSavePath) {
        photoSavePath = photoSavePath.replace("\\", "/");
        String ext = FilenameUtils.getExtension(photoSavePath);
        String path = StringUtils.substringBeforeLast(photoSavePath, "/");
        String name = photoSavePath.substring(photoSavePath.lastIndexOf("/"), photoSavePath.lastIndexOf("."));
        return path + "/preview" + name + "_preview." + ext;
    }

    /**
     * 获取文件的contentType
     *
     * @param mf
     * @return
     */
    public String getContentType(MultipartFile mf) {
        return mf.getContentType();
    }

    /**
     * 获取文件的contentType
     *
     * @param mf
     * @return
     */
    public long getContentLength(MultipartFile mf) {
        return mf.getSize();
    }

    /**
     * 按照特定比例缩放
     *
     * @param sourceW 原图宽度
     * @param sourceH 原图高度
     * @param targetW 目标高度
     * @param targetH 目标宽度
     */
    public Size getZoomSize(Integer sourceW, Integer sourceH, Integer targetW, Integer targetH) {
        double sx = (double) targetW / sourceW;
        double sy = (double) targetH / sourceH;
        if (sx > sy) {
            sx = sy;
            targetW = (int) (sx * sourceW);
        } else {
            sy = sx;
            targetH = (int) (sy * sourceH);
        }
        return new Size(targetW, targetH);
    }

    /**
     * 是否限定图片大小
     *
     * @param sourceWidth  原图片宽度
     * @param sourceHeight 原图片高度
     * @return
     */
    public boolean isLimitSize(int sourceWidth, int sourceHeight) {
        boolean isLimit = "true".equals(optionService.getOption("photo_islimit_size"));
        if (!isLimit) {
            return false;
        }

        Size size = getMaxSize();
        // 原始图片的大小是否超出限定范围
        if (sourceWidth < size.getWidth() && sourceHeight < size.getHeight()) {
            return false;
        }
        return true;
    }

    /**
     * 获取最大size
     *
     * @return
     */
    public Size getMaxSize() {
        String string_ori_width = optionService.getOption("photo_max_width");
        String string_ori_height = optionService.getOption("photo_max_height");
        int MAX_WIDTH = StringUtils.isBlank(string_ori_width) ? DEFAULT_MAX_WIDTH : Integer.parseInt(string_ori_width);
        int MAX_HEIGHT = StringUtils.isBlank(string_ori_height) ? DEFAULT_MAX_HEIGHT : Integer.parseInt(string_ori_height);
        return new Size(MAX_WIDTH, MAX_HEIGHT);

    }

    /**
     * 上传Photo
     *
     * @param image
     * @param filename
     * @return
     * @throws IOException
     * @throws StorageException
     */
    public String uploadPhoto(BufferedImage image, String filename) throws IOException, StorageException {
        String formatName = FilenameUtils.getExtension(filename);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image, formatName, bos);
        byte[] bytearray = bos.toByteArray();
        InputStream inputStream = new ByteArrayInputStream(bytearray);

        String url = storageService.put(filename, inputStream);

        inputStream.close();
        bos.close();
        return url;
    }

    /**
     * 获取图片实体对象
     *
     * @param image
     * @param url
     * @param album
     * @param mf
     * @param photoSaveName
     * @param photoSavePath
     * @return
     */
    public Photo getPhotoEntity(BufferedImage image, String url, long album, MultipartFile mf, String photoSaveName, String previewUrl) {
        Photo photo = new Photo();
        photo.setWidth(image.getWidth());
        photo.setHeight(image.getHeight());
        photo.setAlbum(new Album(album));
        photo.setName(photoSaveName);
        photo.setUrl(url);
        photo.setPreviewUrl(previewUrl);
        photo.setCreateTime(new Date());
        photo.setSize((int) mf.getSize());
        photo = fillExifInfo(mf, photo);
        return photo;
    }

    /**
     * 填充Exif信息
     *
     * @param mf
     * @param photo
     * @return
     */
    public Photo fillExifInfo(MultipartFile mf, Photo photo) {
        return photo;
    }
}
